package com.zhucan.autoconfigure.swagger;

import com.google.common.base.Predicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.paths.AbstractPathProvider;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.List;

import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.builders.PathSelectors.regex;


@EnableConfigurationProperties(SwaggerProperties.class)
@Configuration
@ConditionalOnProperty(prefix = "swagger", value = "enable", havingValue = "true", matchIfMissing = true)
@ConditionalOnClass({Docket.class, ApiInfo.class, ApiKey.class, SecurityContext.class})
@EnableSwagger2
public class SwaggerAutoConfiguration {

  @Autowired
  private SwaggerProperties properties;

  @Bean
  public Docket adminServiceApi() {
    Docket docket = new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(properties.apiInfo())
        .select()
        .apis(RequestHandlerSelectors.basePackage(properties.getBasePackageScan()))
        .paths(PathSelectors.any())
        .build()
        .securitySchemes(newArrayList(properties.apiKey())) // 添加头部token字段
        .securityContexts(newArrayList(securityContext())); // 开启swagger token验证支持
    if (properties.getHost() != null && properties.getHost().length() > 0) {
      docket.host(properties.getHost())
          .pathProvider(new AbstractPathProvider() {
            @Override
            protected String applicationPath() {
              return properties.getPath();
            }

            @Override
            protected String getDocumentationPath() {
              return "/";
            }
          });
    }
    return docket;
  }


  private SecurityContext securityContext() {
    return SecurityContext.builder()
        .securityReferences(defaultAuth())
        .forPaths(securityPaths())
        .build();
  }

  private List<SecurityReference> defaultAuth() {
    AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
    AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
    authorizationScopes[0] = authorizationScope;
    return newArrayList(new SecurityReference("Authorization", authorizationScopes));
  }

  private Predicate<String> securityPaths() {
    return and(regex("/*"), not(regex("/*")));
  }
}
